Release 10.1A: OpenEdge Development:
Programming Interfaces


Example HLC application

This section explains how to use the OpenEdge HLC tank demo application. This application is a prepackaged application that you can use to verify that your HLC environment is set up correctly. The C code and sample output for this example are provided in the $DLC/oebuild/hlc/examples directory on UNIX, and in the %DLC%\oebuild\hlc\examples directory in Windows.

Set up your environment and compile this example before you try to run it to verify that your compiler and the OEBuild utility are working correctly. This also helps you learn how to use HLC in a controlled environment.

This sample application uses OpenEdge to keep track of oil storage tanks. Your Progress procedure calls a C program, AVCALC, to calculate the available capacity for a given tank. Figure 18–7 shows that the tanks are cylindrical, with their axes parallel to the level ground.

Figure 18–7: Tank positioning and orientation

To calculate the available capacity (empty portion) of the tank, you need to know the tank’s diameter, length, and current level of oil. Use the variables in the following formula to calculate the available tank volume:

r

Radius of the tank

length

Length of the tank

level

Level of oil in the tank

For this example, assume there is a tank table for this application that contains the following decimal fields:

radius

Radius of tank

tlength

Length of tank

depth

Level of oil—must be between 0 and (2 . radius)

tavail

Available volume in tank

In addition to these fields, the tank-id character field is used as the primary index.

Figure 18–8 shows the Data Dictionary report for the tank table.

            Default field order: yes
09/10/93                                  Data Dictionary Report                 Page   1
Database: tank
                                   tank File
                                   =========
                   (Flat file containing oil tank information)

Delete Validation
    Criterion:
      Message:
    Field        Type  Ext Dec Format                         Init
    ------------ ----- --- --- ------------------------------ ----------
*   tank-id      char          x(8)
    radius       dec         2 ->>,>>9.99                     0
    tlength      dec         2 ->>,>>9.99                     0
    depth        dec         2 ->>,>>9.99                     0
    tavail       dec         2 ->>,>>9.99  

Index Name   Unique Field Name   Seq Ascending abbreviate
  ------------ ------ ------------ --- --------- ----------
# tank         yes    tank-id        1 yes       yes

Field Validation Criteria, Validation Messages
------------------------------------------------------------------------
depth        :  depth le 2 * (input radius)
                Depth cannot exceed diameter of tank

Help Messages
------------------------------------------------------------------------
tank-id      :  Tank identification number
radius       :  Radius of oil tank
tlength      :  Length of oil Tank
depth        :  Depth of oil in tank.
tavail       :  Available Volume In Tank


                         Data Dictionary Report Legend
             * - Indicates that a field participates in an index
             # - Indicates the primary index for a database file
             M - Indicates that a field is mandatory 

Figure 18–8: Data Dictionary report for tank application

A C function calculates the tavail field from the other three decimal fields (radius, tlength, depth). Figure 18–9 shows the Progress procedure that invokes the C function by calling the HLC routine, AVCALC.

/* calculate available volume for each tank */
DEFINE NEW SHARED BUFFER tankbuf FOR tank.
FOR EACH tankbuf:
  DISPLAY
    radius SPACE(3) tlength SPACE(3) depth SPACE(3)
    tavail WITH CENTERED TITLE "Tank Table".
END.
PAUSE 0.
VIEW FRAME tank-before.
HIDE ALL.

FOR EACH tankbuf:
  DO TRANSACTION:
    CALL AVCALC.
  END.
  DISPLAY
    radius SPACE(3) tlength SPACE(3) depth SPACE(3)
    tavail WITH CENTERED TITLE "After Calculation".
END. 

Figure 18–9: Progress procedure calling HLC routine AVCALC

Make a copy of the HLC dispatch routine, hlprodsp.c, and name it tankdsp.c. Modify the routine so that an entry appears for AVCALC, which calls the C subroutine hlvcalc.

Example hlprodsp.c shows the modifications to the tankdsp.c routine:

hlprodsp.c
#define FUNCTEST(nam, rout)  \
        if (strcmp(nam, pfunnam) == 0) \
            return rout(argc,argv);
/* PROGRAM: PRODSP
 * 
 *   This is the interface to all C routines that 
 *   Progress has associated ’call’ statements to. 
 */
long
PRODSP(pfunnam, argc, argv)     
    char   *pfunnam;   
    /* Name of function to call */
    int     argc;
    char   *argv[];{
    /* Interface to ’tank’ example  */
    FUNCTEST ("AVCALC", hlvcalc);  

    return 1;
} 

The following procedure shows the code for the demo program, hlvcalc.c. The program extracts the radius, length, and level fields from the shared buffer tank, calculates the available volume, and updates the tavail field in the shared buffer tank with the number calculated:

hlvcalc.c
 *    Obtains the height, radius and oil level for the tank
 *    from the shared buffer "tankbuf".
 *    
 *    Calculates the remaining available volume
 *
 *    Update the avail field in the shared buffer "tankbuf" with the
 *    number calculated.
 */
#define  BUFLEN   100
#include <math.h>
#include "hlc.h"
/*NOTE: M_PI_2 is pi/2 constant which may be defined in math.h */
#ifndef M_PI_2
#define M_PI_2   1.570796327
#endif 
extern double asin();

char *fieldnm[] = { "tlength", "depth", "radius"};
char message[80];
int
hlvcalc()
{
   char     buffer[BUFLEN];
   int      unknown = 0, index = 0, varlen = BUFLEN, actlen;
   int      ret;
   double   length, depth, radius, avail;
   int      i;
   int      fldpos;
   double   temp1, temp2;  /* used to simplify calculation */
   /* first, obtain the length, depth and radius from */
   /* the shared buffer "tankbuf".                */
   for (i = 0; i < 3; ++i)
   {
      fldpos = profldix("tankbuf", fieldnm[i]);
      if (fldpos < 0) 
      {
        sprintf(message, "profldix failed on %s for field %s",
                "tankbuf", fieldnm[i]);
        promsgd(message);
        return 1;
       } 
ret = prordbn("tankbuf", fldpos, index,     
                      buffer, &unknown, varlen, &actlen);
      if (ret)
      {
         sprintf(message, "prordbn failed accessing %s . %s",
                  "tankbuf", fieldnm[i]);
         promsgd(message);
         return 1;
      }      
      /* if one of the fields is unknown, set avail field */
      /* to the unknown value                             */
      if (unknown)
      {
         fldpos = profldix("tankbuf", "tavail");
         if (fldpos < 0) 
         {
            sprintf(message, "profldix failed on %s for field %s",
                    "tankbuf", "tavail");
            promsgd(message);
            return 1;
         }          
       ret = prowtbn("tankbuf", fldpos, index, buffer, unknown);
         if (ret)
         {
            sprintf(message, "prowtbn failed, ret = %d", ret);
            promsgd(message); 
            return 1;
         }
         return 0;

      /* convert the character string obtained from */
      /* Progress into a decimal number             */
      buffer[actlen] = ’\0’;

      switch (i)
      {
         case 0: 
                  length = atof(buffer); break;
         case 1:
                  depth  = atof(buffer); break;
         case 2: 
                  radius = atof(buffer); break;
         
         default:
                  break;
      } 

/* Now, calculate the available volume                  */
/* NOTE: M_PI_2 is pi/2 constant defined in math.h */
#ifndef M_PI_2
#define M_PI_2 1.57
#endif
temp1 = 1.0 - depth/radius;
temp2 = temp1 * sqrt(1.0 - temp1 * temp1) + asin(temp1);
avail = length * radius * radius * (temp2 + M_PI_2);

/* Now, put this value in the tavail field in the */
/* "tankbuf" shared buffer                        */
/* get the double into character format */
sprintf(buffer, "%.2f", avail);
fldpos = profldix("tankbuf", "tavail");
if (fldpos < 0) 
{
       sprintf(message, "profldix failed on %s for field %s",
                                      "tankbuf", fieldnm[i]);
       promsgd(message);
       return 1;
} 
ret = prowtbn("tankbuf", fldpos, index, buffer, unknown);
if (ret)
       {
           sprintf(message, "prowtbn failed, ret = %d", ret);
           promsgd(message);
           return 1;
       }
return 0; 


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095